/**
 * 普贴打印小程序 ESC打印 sdk
 * @author zyc
 * @date 2021/05/27
 */
import GBK from './lib/gbk.min';
class putyEscUtils {
	writeArray = [];
	//清空
	clear(){
		this.writeArray = [];
		return this;
	}
	/**
	 * @typeof 初始化
	 * @param width 标签宽度 最大48 
	 */
	init(width) {
		this.clear();
		this.writeArray.push(...[27, 64])
		this.setWidth(width);
		return this;
	}
	/**
	 * @typeof 打印浓度
	 * @param {Int} n表示从浓度1到浓度15
	 */
	setPotency(n) {
		if (!n) {
			n = 1
		}
		if (n < 1) {
			n = 1
		}
		if (n > 15) {
			n = 15
		}
		this.writeArray.push(...[29, 40, 75, 3, 0, 48, 48, parseInt(n)])
		return this;
	}
	/**
	 * @typeof 打印速度
	 * @param {Int} n表示从速度1到速度5
	 */
	setSpeed(n) {
		if (!n) {
			n = 1
		}
		if (n < 1) {
			n = 1
		}
		if (n > 5) {
			n = 5
		}
		this.writeArray.push(...[29, 40, 75, 3, 0, 49, 48, parseInt(n)])
		return this;
	}
	/**
	 * @typeof 纸张类型
	 * @param {Int} n=0：连续纸;n=1：黑标纸;n=2：间隙纸
	 */
	setPaperType(n) {
		if (n == undefined || n == null) {
			n = 2
		}
		if (n < 1) {
			n = 2
		}
		if (n > 3) {
			n = 2
		}
		this.writeArray.push(...[29, 40, 75, 3, 0, 51, 48, parseInt(n)])
		return this;
	}
	/**
	 * @typeof 设置打印宽度
	 * @param {Int} width 宽度
	 */
	setWidth(width){
		if(width >= 48){
			width = 48
		}
		if(width <= 0){
			width = 48
		}
		var nL = parseInt((width * 8) % 256);
		var nH = parseInt((width * 8) / 256);
		this.writeArray.push(...[29,87,nL,nH])
		var maxWidth = 48;
		if(maxWidth - width > 0){
			let offsetLeft = maxWidth - width;
			var nL = parseInt((offsetLeft*8) % 256);
			var nH = parseInt((offsetLeft*8) / 256);
			this.writeArray.push(...[29,76,nL,nH])
		}
		return this;
	}

	/**
	 * @typeof 走纸到下一缝隙
	 */
	next() {
		this.writeArray.push(12)
		return this;
	}
	/**
	 * @typeof 导出数据
	 */
	put() {
		return this.writeArray
	}
	/**
	 * @typeof 打印空白行
	 * @param {number} n 打印几行
	 */
	printWhiteLine(n) {
		if (n < 1) {
			n = 1
		}
		this.writeArray.push(...[21, parseInt(n*8)]);
		return this;
	}
	/** 
	 * 打印文本
	 * @param {string} content 文本内容
	*/
	text(content){
		this.writeArray.push(...GBK.encode(content));
		return this;
	}
	/**
	 * @typeof 打印位置对齐方式
	 * @param {int} n 0左 1中 2右
	 */
	printAlign(n){
		if(!n){n = 48}
		if(n == 1){n = 49}
		if(n == 2){n = 50}
		this.writeArray.push(...[27,97,n])
		return this;
	}
	/**
	 * @typeof 设置行高
	 * @param {int} n 行高
	 */
	lineHeight(n){
		this.writeArray.push(...[27,51,parseInt(n*8)])
		return this;
	}
	/**
	 * @typeof 设置字符大小
	 * @param {int} n 字体大小
	 * 0x12 第一位代表宽度 第二位代表高度
	 */
	fontSize(n){
		// console.log(n)
		// let _n = 0;
		// for(let i = 0;i<n.length;i++){
		// 	_n += n[i] * Math.pow(2,i);
		// }
		// console.log(_n)
		this.writeArray.push(...[29,33,n])
		return this;
	}
	/**
	 * @typeof 选择/取消顺时针旋转90度
	 * @param {boolean} n 旋转还是取消
	 */
	rotate(n){
		n = n ? 49 : 48;
		this.writeArray.push(...[27,86,n])
		return this;
	}
	/**
	 * @typeof 绘制下划线
	 * @param {boolean} n 选择/取消下划线模式
	 */
	underline(n){
		n = n ? 50 : 48
		this.writeArray.push(...[27,45,n])
		return this;
	}
	/**
	 * @typeof 选择或取消加粗模式 
	 * @param {boolean} n 选择/取消加粗模式 
	 */
	fontWeight(n){
		n = n ? 1 : 0
		this.writeArray.push(...[27,69,n])
		return this;
	}
	/**
	 * 
	 * @param {int} 文本间距 n*0.125mm 
	 */
	spacing(n){
		this.writeArray.push(...[27,32,n])
		return this;
	}
	/**
	 * @typeof 一维码 选择条码高度
	 * @param {int} height  条码高度 单位：mm
	 */
	BarCodeHeight(height){
		let _height = parseInt(height * 8);
		this.writeArray.push(...[29,104,_height])
		return this;
	}
	/**
	 *  n 		单基本模块宽度 	双基本模块宽度 
				    窄基本模块（mm） 宽基本模块（mm） 
			2 		0.25 	0.25 	0.625 
			3 		0.375 	0.375 	1.0 
			4 		0.5 	0.5 	1.25 
			5 		0.625 	0.625 	1.625 
			6 		0.75 	0.75 	1.875 
			· 单基本模块条码如下： 
			UPC-A, UPC-E, JAN13 (EAN13), JAN8 (EAN8), CODE93, CODE128 
			· 双基本模块条码如下： 
			CODE39, ITF, CODABAR 
	 * @param {int} n 
	 */
	BarCodeWidth(n){
		this.writeArray.push(...[29,119,n]);
		return this;
	}
	/**
	 * @typeof 设置一维码文本位置
	 * @param {int} n 0不打印 1条码上方 2条码下方 
	 */
	BarCodeTextAlign(n){
		n = n == 0 ? 48 : n;
		n = n == 1 ? 49 : n;
		n = n == 2 ? 50 : n;
		this.writeArray.push(...[29,72,n])
		return this;
	}
	/**
	 * @typeof 导出二维码信息
	 * @param {int} type 类型
	 * 									 65:UPC-A   内容长度 11 - 12
	 * 	                 66:UPC-E   内容长度 11 - 12
	 *                   67:EAN13   内容长度 12 - 13
	 *                   68:EAN8    内容长度 7 - 8
	 *                   69:CODE39  内容长度 1 - 255
	 * 									 70:ITF     内容长度 1 - 255
	 * 									 71:CODABAR 内容长度 1 - 255
	 * 									 72:CODE93  内容长度 1 - 255
	 * 									 73:CODE128 内容长度 2 - 255
	 * @param {string} content 内容
	 */
	BarCodePut(type,content){
		let _content = GBK.encode(content);
		this.writeArray.push(...[29,107,type])
		//CODE128时需要特殊处理
		if(type == 73){
			this.writeArray.push(_content.length + 2)
			this.writeArray.push(...[123,66])
		}else{
			this.writeArray.push(_content.length)
		}
		this.writeArray.push(..._content)
		return this;
	}
	/**
	 * @typeof 一维码
	 * @param {int} type 类型
	 * 									 65:UPC-A   内容长度 11 - 12
	 * 	                 66:UPC-E   内容长度 11 - 12
	 *                   67:EAN13   内容长度 12 - 13
	 *                   68:EAN8    内容长度 7 - 8
	 *                   69:CODE39  内容长度 1 - 255
	 * 									 70:ITF     内容长度 1 - 255
	 * 									 71:CODABAR 内容长度 1 - 255
	 * 									 72:CODE93  内容长度 1 - 255
	 * 									 73:CODE128 内容长度 2 - 255
	 * @param {int} width 	    n 	单基本模块宽度 	双基本模块宽度 
																	窄基本模块（mm） 宽基本模块（mm） 
														2 		0.25 	0.25 	0.625 
														3 		0.375 	0.375 	1.0 
														4 		0.5 	0.5 	1.25 
														5 		0.625 	0.625 	1.625 
														6 		0.75 	0.75 	1.875 
														· 单基本模块条码如下： 
														UPC-A, UPC-E, JAN13 (EAN13), JAN8 (EAN8), CODE93, CODE128 
														· 双基本模块条码如下： 
														CODE39, ITF, CODABAR 
	 * @param {int} height  条码高度 单位：mm
	 * @param {int} textAlign 0不打印 1条码上方 2条码下方 
	 * @param {string} content 内容 
	 */
	BarCode(type,width,height,textAlign,content){
		this.BarCodeHeight(height);
		this.BarCodeWidth(width);
		this.BarCodeTextAlign(textAlign);
		this.BarCodePut(type,content);
		return this;
	}
	/**
	 * @typeof 二维码
	 * @param {string} content 内容
	 * @param {int} size 大小
	 * @param {int} rank      纠错等级
   *                  1:H-可靠性等级(Level H)
   *                  2:Q-高可靠性等级(Level Q)
   *                  3:M-标准等级(Level M)
   *                  4:L-高密度等级(Level L)
	 */
	qrcode(content,size,rank){
		let _content = GBK.encode(content);
		var nL = parseInt(_content.length % 256);
		var nH = parseInt(_content.length / 256);
		if(size>10){size=10}
		this.writeArray.push(...[29,107,97,size,rank,nL,nH])
		this.writeArray.push(..._content);
		return this;
	}
	/**
	 * @typeof 打印位图
   * @typeof 图片打印指令
   * @param imageData canvas rgb数据
   * @param width 宽度 px
   * @param height  高度 px
	 */
	image(imageData,width,height){
		// let imageData = ctx.getImageData(0,0,width,height);
		let pixels = imageData;
		let pixelArr = this.chunkArr(pixels,4);
		let imageBytes = [];
		let pixelIndex = 0;
		let valueArr = [128,64,32,16,8,4,2,1];
		for(let j = 0;j<height;j++){
			imageBytes.push(22);
			imageBytes.push(width / 8)
			for(let i = 0;i<width;i+=8){
				let colorValue = 0;
				for(let k = 0;k<8;k++){
					let pixel = pixelArr[pixelIndex++];
					const r = pixel[0];
					const g = pixel[1];
					const b = pixel[2];
					if(pixel[3] >= 120 && (r+g+b) < 700){
						colorValue += valueArr[k];
					}
				}
				imageBytes.push(colorValue)
			}
		}
		let sl = parseInt(0 % 256);
		let sh = parseInt(0 / 256);
		let nH = parseInt(height / 256);
		let nL = parseInt(height % 256);
		let d4 = parseInt(imageBytes.length / (256 * 256 * 256));
		let d3 = parseInt((imageBytes.length - d4 * (256 * 256 * 256)) / (256 * 256));
		let d2 = parseInt((imageBytes.length - d4 * (256 * 256 * 256) - d3 * (256 * 256)) / 256);
		let d1 = parseInt(imageBytes.length % 256);
		this.writeArray.push(...[23,nL,nH,sl,sh,parseInt(width / 8),1,1,1,d1,d2,d3,d4]);
		this.writeArray.push(...imageBytes);
		return this;
	}

	//回车打印
	enter(){
		this.writeArray.push(10)
		return this;
	}

	//获取打印机状态
	status(){
		this.writeArray.push(...[16,4,1])
		return this;
	}

	// 根据指定个数分割数组
	chunkArr(arr, size) {
		if (!arr.length || !size || size < 1) return []
		let [start, end, result] = [null, null, []]
		for (let i = 0; i < Math.ceil(arr.length / size); i++) {
			start = i * size
			end = start + size
			result.push(arr.slice(start, end))
		}
		return result
	}
}

export default new putyEscUtils();